package com.example.everying.service.user.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.everying.constant.OrderConstants;
import com.example.everying.mapper.user.ActivityParticipationMapper;
import com.example.everying.mapper.user.PointsAccountMapper;
import com.example.everying.mapper.user.PointsTransactionMapper;
import com.example.everying.mapper.user.UserMapper;
import com.example.everying.model.entity.user.ActivityParticipation;
import com.example.everying.model.entity.user.PointsAccount;
import com.example.everying.model.entity.user.PointsTransaction;
import com.example.everying.model.entity.user.UserEntity;
import com.example.everying.model.vo.points.PointsAccountVo;
import com.example.everying.service.user.ActivityParticipationService;
import com.example.everying.service.user.PointsAccountService;
import com.example.everying.service.user.PointsTransactionService;
import com.example.everying.service.user.UserService;
import com.example.everying.utils.WeChatUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.Year;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * 积分账户Service实现类
 */
@Service
@Slf4j
public class PointsAccountServiceImpl extends ServiceImpl<PointsAccountMapper, PointsAccount> implements PointsAccountService {

    @Autowired
    private PointsTransactionService pointsTransactionService;
    @Autowired
    private UserService userService;
    @Autowired
    private ActivityParticipationService activityParticipationService;
    @Autowired
    private UserMapper userMapper;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void addPoints(String userId, Integer points, String remark, String type) {
        log.info("开始增加积分 -- userId:{},points:{},remark:{}", userId, points, remark);
        PointsAccount pointsAccount = getByUid(userId);
        if (pointsAccount == null) {
            createPointsAccount(userId, points);
        } else {
            pointsAccount.setTotalPoints(pointsAccount.getTotalPoints() + points);
            pointsAccount.setAvailablePoints(pointsAccount.getAvailablePoints() + points);
            pointsAccount.setUpdateTime(LocalDateTime.now());
            baseMapper.updateById(pointsAccount);
            // 添加积分记录
            PointsTransaction pointsTransaction = new PointsTransaction();
            pointsTransaction.setUserId(userId);
            pointsTransaction.setTransactionNo(WeChatUtil.generateOrderTradeNumber(OrderConstants.TRANSACTION_TYPE_PREFIX_POINTS));
            pointsTransaction.setPointsChange(points);
            pointsTransaction.setTransactionType(1);
            if (type != null) {
                pointsTransaction.setActivityType(type);
            }
            pointsTransaction.setStatus(1);
            pointsTransaction.setDescription(remark);
            pointsTransaction.setCreateTime(LocalDateTime.now());
            pointsTransactionService.save(pointsTransaction);
        }
    }
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void addPointsAndParticipation(String userId, Integer points, String remark, String type, ActivityParticipation activityParticipation) {
        log.info("开始增加积分 -- userId:{},points:{},remark:{}", userId, points, remark);
        PointsAccount pointsAccount = getByUid(userId);
        if (pointsAccount == null) {
            createPointsAccount(userId, points);
        } else {
            pointsAccount.setTotalPoints(pointsAccount.getTotalPoints() + points);
            pointsAccount.setAvailablePoints(pointsAccount.getAvailablePoints() + points);
            pointsAccount.setUpdateTime(LocalDateTime.now());
            baseMapper.updateById(pointsAccount);
            // 添加积分记录
            PointsTransaction pointsTransaction = new PointsTransaction();
            pointsTransaction.setUserId(userId);
            pointsTransaction.setTransactionNo(WeChatUtil.generateOrderTradeNumber(OrderConstants.TRANSACTION_TYPE_PREFIX_POINTS));
            pointsTransaction.setPointsChange(points);
            pointsTransaction.setTransactionType(1);
            if (type != null) {
                pointsTransaction.setActivityType(type);
            }
            pointsTransaction.setStatus(1);
            pointsTransaction.setDescription(remark);
            pointsTransaction.setCreateTime(LocalDateTime.now());
            pointsTransactionService.save(pointsTransaction);

            // 更新流水记录
            activityParticipation.setPointsId(pointsTransaction.getId());
            activityParticipationService.updateById(activityParticipation);
        }
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void minusPoints(String userId, Integer points, String remark) {
        log.info("开始减少积分 -- userId:{},points:{},remark:{}", userId, points, remark);
        PointsAccount pointsAccount = getByUid(userId);
        if (pointsAccount == null) {
            createPointsAccount(userId, points);
            baseMapper.insert(pointsAccount);
        } else {
            pointsAccount.setTotalPoints(pointsAccount.getTotalPoints() - points);
            pointsAccount.setAvailablePoints(pointsAccount.getAvailablePoints() - points);
            pointsAccount.setUpdateTime(LocalDateTime.now());
            baseMapper.updateById(pointsAccount);
            // 添加积分记录
            PointsTransaction pointsTransaction = new PointsTransaction();
            pointsTransaction.setUserId(userId);
            pointsTransaction.setPointsChange(points);
            pointsTransaction.setTransactionNo(WeChatUtil.generateOrderTradeNumber(OrderConstants.TRANSACTION_TYPE_PREFIX_POINTS));
            pointsTransaction.setTransactionType(2);
            pointsTransaction.setStatus(1);
            pointsTransaction.setDescription(remark);
            pointsTransaction.setCreateTime(LocalDateTime.now());
            pointsTransactionService.save(pointsTransaction);
        }
    }

    @Override
    public PointsAccountVo getByUid(String userId) {
        QueryWrapper<PointsAccount> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("user_id", userId);
        PointsAccount pointsAccount = baseMapper.selectOne(queryWrapper);
        PointsAccountVo pointsAccountVo = new PointsAccountVo();
        BeanUtils.copyProperties(pointsAccount, pointsAccountVo);
//        pointsAccountVo.setPointsAccount(pointsAccount);
        // 传一个每一年的最后一天
        pointsAccountVo.setDate(Year.now().atDay(365).plusDays(1));  // 12月31日);
        return pointsAccountVo;
    }

    /**
     * @param userId
     * @return
     */
    @Override
    public boolean createPointsAccount(String userId, Integer points) {
        PointsAccount pointsAccount;
        pointsAccount = new PointsAccount();
        pointsAccount.setUserId(userId);
        pointsAccount.setTotalPoints(points);
        pointsAccount.setAvailablePoints(points);
        pointsAccount.setFrozenPoints(0);
        pointsAccount.setCreateTime(LocalDateTime.now());
        pointsAccount.setUpdateTime(LocalDateTime.now());
        pointsAccount.setVersion(0);
        return baseMapper.insert(pointsAccount) > 0;
    }

    /**
     * 更新用户积分（乐观锁保证并发安全）
     *
     * @param userId       用户 ID
     * @param pointsChange 积分变动值（正负）
     * @return 是否更新成功
     */
    @Transactional
    public boolean updatePoints(String userId, int pointsChange) {
        // 判断当天是否已签到
        LocalDate today = LocalDate.now();
        LocalDateTime todayStart = today.atStartOfDay(); // 当天 00:00:00
        LocalDateTime todayEnd = today.plusDays(1).atStartOfDay(); // 次日 00:00:00（用于范围查询）

        // 查询当天是否已有签到奖励记录
        int count = Math.toIntExact(pointsTransactionService.lambdaQuery()
                .eq(PointsTransaction::getUserId, userId) // 用户ID
                .eq(PointsTransaction::getTransactionType, 1) // 交易类型：1-增加奖励
                .like(PointsTransaction::getDescription, "签到") // 描述：签到
                .ge(PointsTransaction::getCreateTime, todayStart) // 创建时间 >= 当天0点
                .lt(PointsTransaction::getCreateTime, todayEnd) // 创建时间 < 次日0点
                .count());

        if (count > 0) {
            // 当天已签到，不重复发放奖励
            log.warn("用户 {} 当天已签到，拒绝重复发放奖励", userId);
            return false;
        }

        // 1. 查询用户积分账户
        PointsAccount account = lambdaQuery()
                .eq(PointsAccount::getUserId, userId)
                .one();

        if (account == null) {
            // 账户不存在，初始化（可根据业务需求决定是否自动创建）
            account = new PointsAccount();
            account.setUserId(userId);
            account.setTotalPoints(0);
            account.setAvailablePoints(0);
            account.setFrozenPoints(0);
            account.setCreateTime(LocalDateTime.now());
            account.setUpdateTime(LocalDateTime.now());
            save(account);
        }

        // 2. 计算新积分
        int newTotal = account.getTotalPoints() + pointsChange;
        int newAvailable = account.getAvailablePoints() + pointsChange;

        // 3. 乐观锁更新
        return lambdaUpdate()
                .set(PointsAccount::getTotalPoints, newTotal)
                .set(PointsAccount::getAvailablePoints, newAvailable)
                .eq(PointsAccount::getUserId, userId)
//                .eq(PointsAccount::getVersion, account.getVersion()) // 乐观锁条件
                .set(PointsAccount::getVersion, 0) // 版本号自增
                .set(PointsAccount::getUpdateTime, LocalDateTime.now()) // 修改时间
                .update();
    }

    @Override
    @Transactional
    public int clearPoints(LocalDateTime time) {
        LambdaUpdateWrapper<PointsAccount> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.lt(PointsAccount::getUpdateTime, time)
                .set(PointsAccount::getTotalPoints, 0)
                .set(PointsAccount::getAvailablePoints, 0)
                .set(PointsAccount::getFrozenPoints, 0);
        int update = baseMapper.update(updateWrapper);


        return update;
    }
    @Override
    public void ccccc() {
        // 查询所有积分账户
        QueryWrapper<PointsAccount> queryWrapper = new QueryWrapper<>();
        List<PointsAccount> list = baseMapper.selectList(queryWrapper);
        Set<String> userIds = list.stream().map(PointsAccount::getUserId).collect(Collectors.toSet());
        
        // 获取所有用户
        List<UserEntity> userEntities = userService.list();
        Set<String> allUserIds = userEntities.stream().map(UserEntity::getId).collect(Collectors.toSet());
        
        // 找出没有积分账户的用户
        allUserIds.removeAll(userIds);
        
        // 为这些用户创建积分账户
        for (String userId : allUserIds) {
            PointsAccount pointsAccount = new PointsAccount();
            pointsAccount.setUserId(userId);
            pointsAccount.setTotalPoints(0);
            pointsAccount.setAvailablePoints(0);
            pointsAccount.setFrozenPoints(0);
            pointsAccount.setCreateTime(LocalDateTime.now());
            pointsAccount.setUpdateTime(LocalDateTime.now());
            pointsAccount.setVersion(0);
            baseMapper.insert(pointsAccount);
        }
    }

    @Override
    public boolean activityList(List<String> userId , Integer points) {
        List<String> targetUserIds;
        if (userId == null || userId.isEmpty()) {
            targetUserIds = userMapper.listAllUserIds();
        } else {
            targetUserIds = userId;
        }

        new Thread(() -> {
            for (String id : targetUserIds) {
                addPoints(id, points, "赠送活动积分", "");
            }
        }).start();
        return true;
    }
}
